package com.ezandroid.alphago.engine;

import java.util.HashSet;
import java.util.Set;

/**
 * Track a single-color chain of stones
 */
public class Chain implements Cloneable {

    private StoneColor mStoneColor;
    private Set<Stone> mStones;
    private Set<Intersection> mLiberties;

    Chain(StoneColor c) {
        mStoneColor = c;
        mStones = new HashSet<>();
        mLiberties = new HashSet<>();
    }

    @Override
    protected Chain clone() throws CloneNotSupportedException {
        Chain chain = (Chain) super.clone();
        chain.mStoneColor = mStoneColor;
        chain.mStones = new HashSet<>();
        chain.mLiberties = new HashSet<>();
        for (Stone stone : mStones) {
            chain.mStones.add(stone.clone());
        }
        for (Intersection intersection : mLiberties) {
            chain.mLiberties.add(intersection.clone());
        }
        return chain;
    }

    /**
     * Public access to the set of stones
     */
    public Set<Stone> getStones() {
        return mStones;
    }

    /**
     * Public access to the set of liberties
     */
    public Set<Intersection> getLiberties() {
        return mLiberties;
    }

    /**
     * Public access to the color
     */
    public StoneColor getStoneColor() {
        return mStoneColor;
    }

    /**
     * Returns number of stones in chain
     */
    public int size() {
        return mStones.size();
    }

    /**
     * Adds the supplied stone to this chain, updating liberties
     */
    public void add(Stone stone, Set<Intersection> newLiberties) {
        if (mStoneColor != stone.color) {
            throw new IllegalArgumentException("Can not add stone of color " + stone
                    .color +
                    " to chain of color " + mStoneColor);
        }
        mLiberties.remove(stone.intersection);
        mLiberties.addAll(newLiberties);
        mStones.add(stone);
    }

    /**
     * Copies all stones and liberties from the supplied chain to this; does not modify
     * argument
     */
    public void merge(Chain chain) {
        if (mStoneColor != chain.mStoneColor) {
            throw new IllegalArgumentException("Can not merge chain of color " + chain
                    .mStoneColor +
                    " to chain of color " + mStoneColor);
        }
        mStones.addAll(chain.mStones);
        mLiberties.addAll(chain.mLiberties);
    }

    public void addLiberty(Intersection intersection) {
        mLiberties.add(intersection);
    }

    /**
     * Removes the supplied liberty
     */
    public void removeLiberty(Intersection intersection) {
        mLiberties.remove(intersection);
    }

    /**
     * Check if the supplied coords are the last liberty for this group (i.e. a stone here
     * kills)
     */
    public boolean isLastLiberty(Intersection intersection) {
        return mLiberties.size() == 1 && mLiberties.contains(intersection);
    }
}
